﻿using System;
using System.Collections.Generic;
using GodProject.peoples;

namespace GodProject.console
{
  /// <summary>
  ///  Coordinate peoples creation and output
  /// </summary>
  class GodConsoleController
  {
    /// <summary>
    /// Used for writing result of creation
    /// </summary>
    private readonly GodConsoleWriter _writer;

    /// <summary>
    /// Default constructor
    /// </summary>
    /// <param name="writer">writer to be used for printing</param>
    public GodConsoleController(GodConsoleWriter writer)
    {
      _writer = writer;
    }

    /// <summary>
    /// Stores dictionary of positions for "pair" people will be created secondly. 
    /// </summary>
    private readonly Dictionary<Human, GodConsolePosition> _positionsForPair = new Dictionary<Human, GodConsolePosition>();

    #region humans creation and printing
    /// <summary>
    /// Creates number of people pairs
    /// </summary>
    /// <param name="count">number of pairs to be created</param>
    public void StartCreation(int count)
    {
      _positionsForPair.Clear();
      CreateHumansWithoutPair(count);
      int lastTopPosition = Console.CursorTop;
      CreatePairsForGeneratedHumans();
      Console.CursorTop = lastTopPosition + 1;
      Console.CursorLeft = 0;
      Console.ResetColor();
      God.Instance.PrintTotalMoneyToFile();
    }

    /// <summary>
    /// Create and writes to console humans without pair
    /// </summary>
    /// <param name="count">number of humans to be created</param>
    private void CreateHumansWithoutPair(int count)
    {
      for (int i = 0; i < count; i++)
      {
        CreateAndWriteHuman();
      }
    }

    /// <summary>
    /// Create and write to console pair-human for firstly generated humans
    /// </summary>
    private void CreatePairsForGeneratedHumans()
    {
      foreach (KeyValuePair<Human, GodConsolePosition> entry in _positionsForPair)
      {
        Human h = entry.Key;
        GodConsolePosition position = entry.Value;
        CreatePrintPairHuman(h, position);
      }
    }

    /// <summary>
    /// Creates and writes single human
    /// </summary>
    private void CreateAndWriteHuman()
    {
      Human human = God.Instance.CreateHuman();
      _writer.WriteNonPairToConsole(human);
      _positionsForPair.Add(human, new GodConsolePosition(Console.CursorTop, Console.CursorLeft));
      _writer.WriteReservedLinesForFuturePair();
    }

    /// <summary>
    /// Creates and writes single pair-human for previously created human
    /// </summary>
    /// <param name="human">human, whose pair will be created</param>
    /// <param name="position">position on console, where printing will start</param>
    private void CreatePrintPairHuman(Human human, GodConsolePosition position)
    {
      Human pairHuman = God.Instance.CreatePair(human);
      _writer.WritePairHumanToConsole(pairHuman, 0, position.Top + 1);
    }

    #endregion humans creation and printing


    #region auxiliary classes
    /// <summary>
    /// Represents position on console. 
    /// </summary>
    private class GodConsolePosition
    {
      /// <summary>
      /// Top position
      /// </summary>
      internal int Top { get; private set; }

      /// <summary>
      /// Left position
      /// </summary>
      internal int Left { get; private set; }

      /// <summary>
      /// Constructor
      /// </summary>
      /// <param name="top">top position</param>
      /// <param name="left">left position</param>
      public GodConsolePosition(int top, int left)
      {
        Top = top;
        Left = left;
      }
    }
    #endregion auxiliary classes

  }
}
